package psd.core;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import javax.xml.namespace.QName;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Shell;

import psd.config.ConfigurationReader;
import psd.model.Bug;
import psd.model.ModelGenerator;
import psd.model.RuleSet;
import psd.model.RuleSetManager;
import psd.model.StadisticManager;
import psd.model.Prolog.PrologModelGenerator;
import psd.scala.*;
import psd.scala.rules.ScalaRules;
import psd.service.StoreStadisticService;
import psd.service.StoreStadisticServiceService;



public class CodeEvaluator {

	private IJavaProject currentProject;
	
	public CodeEvaluator(IJavaProject project) {
		currentProject = project;
	}

	public void FindProblems() {
		intializeProperties();
	 
		
		ProgressMonitorDialog dialog = new ProgressMonitorDialog(new Shell());
		try {
			dialog.run(true, false, new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor) {
					try {
						IProject iproject = currentProject.getProject();
						if (iproject.isOpen()
								&& iproject
										.isNatureEnabled("org.eclipse.jdt.core.javanature")) {

							IPackageFragment[] packages = JavaCore.create(
									iproject).getPackageFragments();

							monitor.beginTask("AST parsing", packages.length);
							
							/*	PROLOG */
							//ModelGenerator model = new PrologModelGenerator();
							
							/* SCALA */
							FactDb fdb = new FactDb();
							ModelGenerator model = new ScalaModelGenerator(fdb);
							
							/* Recorrido de archivos del proyecto */
							for (IPackageFragment mypackage : packages) {
								if (mypackage.getKind() == IPackageFragmentRoot.K_SOURCE) {
									for (ICompilationUnit unit : mypackage
											.getCompilationUnits()) {
										CompilationUnitManager.Instance().set_currentCompilationUnit(unit);
										IResource resource =  CompilationUnitManager.Instance().get_currentCompilationUnit().getCorrespondingResource();
										resource.deleteMarkers("psd.codeProblems", true, IResource.DEPTH_INFINITE);
										CodeParser parser = new CodeParser();
										CompilationUnit parse = parser.Parse();
										
										model.process(parse);
									}
								}
								monitor.worked(1);
							}
							
							/* Ejecucion reglas SCALA */
							ScalaRules sr = new ScalaRules();
							sr.executeRules(fdb);
							
							
							/***SECCION PROLOG***/
							//RuleSet ruleSet = InitializeRules();
							//Execute PSD analysis
							//ruleSet.runRules(monitor);
							
							/**ESTADISTICAS SE GUARDAN EN SERVIDOR WEB*/
							/*monitor.beginTask("Storing Stadistics", 1);							
					
							String stadistics = StadisticManager.getInstance().getStadistics();
							
							StoreStadisticService psdService = null;
							try{
								psdService = getPSDService();
								psdService.storeStadistic(stadistics);
								StadisticManager.getInstance().deleteStadisticsFile();
							} catch (Exception e) {
								e.printStackTrace();
							}
							//Send PSD stadistics to service
							*/
							
							monitor.worked(1);
							monitor.beginTask("Done", 0);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

					monitor.done();
				}
			});
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void intializeProperties() {
		Properties pr=System.getProperties();
		String home = System.getProperty("user.home");
		home = home + "\\PSD\\config.properties";
		Properties props = new Properties();
		
		try {
			props.load(new BufferedReader(new FileReader(home)));
			
			for(Enumeration<Object> e=pr.keys();e.hasMoreElements();){
				Object o= e.nextElement();
				props.put(o, pr.get(o));
			}
			System.setProperties(props);
			
		} catch (FileNotFoundException e1) {
			MessageDialog.openInformation(null, "PSD","No se encuentra el archivo de configuracion!!!");
		} catch (IOException e1) {
			MessageDialog.openInformation(null, "PSD","No se encuentra el archivo de configuracion!!!");
		}
	}

	private RuleSet InitializeRules() {
		RuleSetManager reader = new RuleSetManager(
				ConfigurationReader.Instance().getProperty(
						"ruleSetPath"));
		RuleSet ruleSet = reader.ReadRules();
		//Get latest rules definition file
		StoreStadisticService psdService = null;
		String newRuleset = "";
		try
		{
			psdService = getPSDService();
			if(psdService != null)
				newRuleset = psdService.updateRulesFile(ruleSet.getVersion());
			
			if( newRuleset.length() > 0)
			{
				reader.WriteRule(newRuleset);
				ruleSet = reader.ReadRules();
			}	
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
				
		return ruleSet;
	}
	
	private StoreStadisticService getPSDService() {
		
		URL serviceURL;
		try {
			serviceURL = new URL (ConfigurationReader.Instance().getProperty("psdServiceUrl"));
			QName serviceName = new QName("http://DefaultNamespace","StoreStadisticServiceService");
			StoreStadisticServiceService sh =  new StoreStadisticServiceService(serviceURL,serviceName);
			StoreStadisticService shs = sh.getStoreStadisticService();
			return shs;
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (javax.xml.ws.WebServiceException e2)
		{
			
		}
			
		return null;
	}
}
